home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / mipsABI / examples / sup / PORT / step06 / supcmain.c < prev    next >
Encoding:
Text File  |  1994-08-02  |  22.1 KB  |  740 lines

  1. /*
  2.  * Copyright (c) 1992 Carnegie Mellon University
  3.  * All Rights Reserved.
  4.  * 
  5.  * Permission to use, copy, modify and distribute this software and its
  6.  * documentation is hereby granted, provided that both the copyright
  7.  * notice and this permission notice appear in all copies of the
  8.  * software, derivative works or modified versions, and any portions
  9.  * thereof, and that both notices appear in supporting documentation.
  10.  *
  11.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  12.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  13.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  14.  *
  15.  * Carnegie Mellon requests users of this software to return to
  16.  *
  17.  *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
  18.  *  School of Computer Science
  19.  *  Carnegie Mellon University
  20.  *  Pittsburgh PA 15213-3890
  21.  *
  22.  * any improvements or extensions that they make and grant Carnegie Mellon
  23.  * the rights to redistribute these changes.
  24.  */
  25. /*
  26.  *    sup -- Software Upgrade Protocol client process
  27.  *
  28.  *    Usage:  sup [ flags ] [ supfile ] [ collection ... ]
  29.  *
  30.  *    The only required argument to sup is the name of a supfile.  It
  31.  *    must either be given explicitly on the command line, or the -s
  32.  *    flag must be specified.  If the -s flag is given, the system
  33.  *    supfile will be used and a supfile command argument should not be
  34.  *    specified.  The list of collections is optional and if specified
  35.  *    will be the only collections upgraded.  The following flags affect
  36.  *    all collections specified.
  37.  *
  38.  *    -s    "system upgrade" flag
  39.  *            As described above.
  40.  *
  41.  *    -t    "upgrade time" flag
  42.  *            When this flag is given, Sup will print the time
  43.  *            that each collection was last upgraded, rather than
  44.  *            performing actual upgrades.
  45.  *
  46.  *    -R    "resource pause" flag
  47.  *            Sup will not disable resource pausing and will not
  48.  *            make filesystem space checks.
  49.  *
  50.  *    -N    "debug network" flag
  51.  *            Sup will trace messages sent and received that
  52.  *            implement the Sup network protocol.
  53.  *
  54.  *    -P    "debug ports" flag
  55.  *                Sup will use a set of non-privileged network
  56.  *            ports reserved for debugging purposes.
  57.  *
  58.  *    -X    "crosspatch" flag
  59.  *                Sup is being run remotely with a crosspatch.
  60.  *            Need to be carefull as we may be running as root
  61.  *            instead of collection owner.
  62.  *
  63.  *    The remaining flags affect all collections unless an explicit list
  64.  *    of collections are given with the flags.  Multiple flags may be
  65.  *    specified together that affect the same collections.  For the sake
  66.  *    of convience, any flags that always affect all collections can be
  67.  *    specified with flags that affect only some collections.  For
  68.  *    example, "sup -sde=coll1,coll2" would perform a system upgrade,
  69.  *    and the first two collections would allow both file deletions and
  70.  *    command executions.  Note that this is not the same command as
  71.  *    "sup -sde=coll1 coll2", which would perform a system upgrade of
  72.  *    just the coll2 collection and would ignore the flags given for the
  73.  *    coll1 collection.
  74.  *
  75.  *    -a    "all files" flag
  76.  *            All files in the collection will be copied from
  77.  *            the repository, regardless of their status on the
  78.  *            current machine.  Because of this, it is a very
  79.  *            expensive operation and should only be done for
  80.  *            small collections if data corruption is suspected
  81.  *            and been confirmed.  In most cases, the -o flag
  82.  *            should be sufficient.
  83.  *
  84.  *    -b    "backup files" flag
  85.  *            If the -b flag if given, or the "backup" supfile
  86.  *            option is specified, the contents of regular files
  87.  *            on the local system will be saved before they are
  88.  *            overwritten with new data.  The data will be saved
  89.  *            in a subdirectory called "BACKUP" in the directory
  90.  *            containing the original version of the file, in a
  91.  *            file with the same non-directory part of the file
  92.  *            name.  The files to backup are specified by the
  93.  *            list file on the repository.
  94.  *
  95.  *    -B    "don't backup files" flag
  96.  *            The -B flag overrides and disables the -b flag and
  97.  *            the "backup" supfile option.
  98.  *
  99.  *    -d    "delete files" flag
  100.  *            Files that are no longer in the collection on the
  101.  *            repository will be deleted if present on the local
  102.  *            machine.  This may also be specified in a supfile
  103.  *            with the "delete" option.
  104.  *
  105.  *    -D    "don't delete files" flag
  106.  *            The -D flag overrides and disables the -d flag and
  107.  *            the "delete" supfile option.
  108.  *
  109.  *    -e    "execute files" flag
  110.  *            Sup will execute commands sent from the repository
  111.  *            that should be run when a file is upgraded.  If
  112.  *            the -e flag is omitted, Sup will print a message
  113.  *            that specifies the command to execute.  This may
  114.  *            also be specified in a supfile with the "execute"
  115.  *            option.
  116.  *
  117.  *    -E    "don't execute files" flag
  118.  *            The -E flag overrides and disables the -e flag and
  119.  *            the "execute" supfile option.
  120.  *
  121.  *    -f    "file listing" flag
  122.  *            A "list-only" upgrade will be performed.  Messages
  123.  *            will be printed that indicate what would happen if
  124.  *            an actual upgrade were done.
  125.  *
  126.  *    -k    "keep newer files" flag
  127.  *            The -k flag, or "keep" supfile option, will cause
  128.  *            Sup to check to see whether there is a newer file on
  129.  *            the local disk before updating files.  Only files
  130.  *            which are newer on the repository will be updated.
  131.  *
  132.  *    -K    "don't keep newer files" flag
  133.  *            The -K flag overrides and disables the -k flag and
  134.  *            the "keep" supfile option.
  135.  *
  136.  *    -l    "local upgrade" flag
  137.  *            Normally, Sup will not upgrade a collection if the
  138.  *            repository is on the same machine.  This allows
  139.  *            users to run upgrades on all machines without
  140.  *            having to make special checks for the repository
  141.  *            machine.  If the -l flag is specified, collections
  142.  *            will be upgraded even if the repository is local.
  143.  *
  144.  *    -m    "mail" flag
  145.  *            Normally, Sup used standard output for messages.
  146.  *            If the -m flag if given, Sup will send mail to the
  147.  *            user running Sup, or a user specified with the
  148.  *            "notify" supfile option, that contains messages
  149.  *            printed by Sup.
  150.  *
  151.  *    -o    "old files" flag
  152.  *            Sup will normally only upgrade files that have
  153.  *            changed on the repository since the last time an
  154.  *            upgrade was performed.  The -o flag, or the "old"
  155.  *            supfile option, will cause Sup to check all files
  156.  *            in the collection for changes instead of just the
  157.  *            new ones.
  158.  *
  159.  *    -O    "not old files" flag
  160.  *            The -O flag overrides and disables the -o flag and
  161.  *            the "old" supfile option.
  162.  *
  163.  *    -v    "verbose" flag
  164.  *            Normally, Sup will only print messages if there
  165.  *            are problems.  This flag causes Sup to also print
  166.  *            messages during normal progress showing what Sup
  167.  *            is doing.
  168.  *
  169.  **********************************************************************
  170.  * HISTORY
  171.  *
  172.  * 7-July-93  Nate Williams at Montana State University
  173.  *    Modified SUP to use gzip based compression when sending files
  174.  *    across the network to save BandWidth
  175.  *
  176.  * $Log: supcmain.c,v $
  177.  * Revision 1.3  1993/08/04  17:46:17  brezak
  178.  * Changes from nate for gzip'ed sup
  179.  *
  180.  * Revision 1.2  1993/05/24  17:57:28  brezak
  181.  * Remove netcrypt.c. Remove unneeded files. Cleanup make.
  182.  *
  183.  * Revision 1.1.1.1  1993/05/21  14:52:18  cgd
  184.  * initial import of CMU's SUP to NetBSD
  185.  *
  186.  * Revision 1.6  92/08/11  12:06:59  mrt
  187.  *     Merged in Brad's changes. Made resource pausing code conditional
  188.  *     on MACH, rather than CMUCS. Fixed some calls to sprintf to
  189.  *     return void.
  190.  *     [92/08/09            mrt]
  191.  * 
  192.  * Revision 1.5  92/02/08  19:01:18  mja
  193.  *     Correct oldsigsys type when ANSI C.
  194.  *     [92/02/08  18:59:47  mja]
  195.  * 
  196.  * Revision 1.4  92/02/08  18:24:01  mja
  197.  *     Added -k and -K switches.
  198.  *     [92/01/17            vdelvecc]
  199.  * 
  200.  * 27-Dec-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  201.  *    Added crosspatch support (is currently ignored).
  202.  *
  203.  * 28-Jun-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  204.  *    Added code for "release" support.
  205.  *
  206.  * 25-May-87  Doug Philips (dwp) at Carnegie-Mellon University
  207.  *    Split into several files.  This is the main program and
  208.  *    command line processing and old history log. [V5.21]
  209.  *
  210.  * 21-May-87  Chriss Stephens (chriss) at Carnegie Mellon University
  211.  *    Merged divergent CS and ECE versions. ifdeffed out the resource
  212.  *    pausing code - only compiled in if CMUCS defined. [V5.21a]
  213.  *
  214.  * 20-May-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  215.  *    Removed support for version 3 of SUP protocol.  Added changes
  216.  *    to make lint happy.  Added calls to new logging routines. [V5.20]
  217.  *
  218.  * 01-Apr-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  219.  *    Added -R switch to reenable resource pausing, which is currently
  220.  *    disabled by default.  Added code to check for free disk space
  221.  *    available on the target filesystem so that sup shouldn't run the
  222.  *    system out of disk space as frequently. [V5.19]
  223.  *
  224.  * 19-Sep-86  Mike Accetta (mja) at Carnegie-Mellon University
  225.  *    Changed default supfile name for system collections when -t
  226.  *    is specified to use FILESUPTDEFAULT; added missing new-line
  227.  *    in retry message. [V5.18]
  228.  *
  229.  * 21-Jun-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  230.  *    Missed a caller to a routine which had an extra argument added
  231.  *    to it last edit. [V5.17]
  232.  *
  233.  * 07-Jun-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  234.  *    Changed getcoll() so that fatal errors are checked immediately
  235.  *    instead of after sleeping for a little while.  Changed all
  236.  *    rm -rf commands to rmdir since the Mach folks keep deleting
  237.  *    their root and /usr directory trees.  Reversed the order of
  238.  *    delete commands to that directories will possibly empty so
  239.  *    that the rmdir's work. [V5.16]
  240.  *
  241.  * 30-May-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  242.  *    Changed temporary file names to #n.sup format. [V5.15]
  243.  *
  244.  * 19-Feb-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  245.  *    Moved PGMVERSION to supvers.c module. [V5.14]
  246.  *
  247.  * 06-Feb-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  248.  *    Added check for file type before unlink when receiving a
  249.  *    symbolic link.  Now runs "rm -rf" if the file type is a
  250.  *    directory. [V5.13]
  251.  *
  252.  * 03-Feb-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  253.  *    Fixed small bug in signon that didn't retry connections if an
  254.  *    error occured on the first attempt to connect. [V5.12]
  255.  *
  256.  * 26-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  257.  *    New command interface.  Added -bBDEO flags and "delete",
  258.  *    "execute" and "old" supfile options.  Changed -d to work
  259.  *    correctly without implying -o. [V5.11]
  260.  *
  261.  * 21-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  262.  *    Fix incorrect check for supfile changing.  Flush output buffers
  263.  *    before restart. [V5.10]
  264.  *
  265.  * 17-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  266.  *    Add call to requestend() after connection errors are retried to
  267.  *    free file descriptors. [V5.9]
  268.  *
  269.  * 15-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  270.  *    Fix SERIOUS merge error from previous edit.  Added notify
  271.  *    when execute command fails. [V5.8]
  272.  *
  273.  * 11-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  274.  *    Changed ugconvert to clear setuid/setgid bits if it doesn't use
  275.  *    the user and group specified by the remote system.  Changed
  276.  *    execute code to invalidate collection if execute command returns
  277.  *    with a non-zero exit status.  Added support for execv() of
  278.  *    original arguments of supfile is upgraded sucessfully.  Changed
  279.  *    copyfile to always use a temp file if possible. [V5.7]
  280.  *
  281.  * 04-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  282.  *    Added support for fileserver busy messages and new nameserver
  283.  *    protocol to support multiple repositories per collection.
  284.  *    Added code to lock collections with lock files. [V5.6]
  285.  *
  286.  * 29-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  287.  *    Major rewrite for protocol version 4. [V4.5]
  288.  *
  289.  * 12-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  290.  *    Changed to check for DIFFERENT mtime (again). [V3.4]
  291.  *
  292.  * 08-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  293.  *    Replaced [ug]convert routines with ugconvert routine so that an
  294.  *    appropriate group will be used if the default user is used.
  295.  *    Changed switch parsing to allow multiple switches to be specified
  296.  *    at the same time. [V3.3]
  297.  *
  298.  * 04-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  299.  *    Added test to request a new copy of an old file that already
  300.  *    exists if the mtime is different. [V3.2]
  301.  *
  302.  * 24-Nov-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  303.  *    Added -l switch to enable upgrades from local repositories.
  304.  *
  305.  * 03-Nov-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  306.  *    Minor change in order -t prints so that columns line up.
  307.  *
  308.  * 22-Oct-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  309.  *    Added code to implement retry flag and pass this on to request().
  310.  *
  311.  * 22-Sep-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  312.  *    Merged 4.1 and 4.2 versions together.
  313.  *
  314.  * 04-Jun-85  Steven Shafer (sas) at Carnegie-Mellon University
  315.  *    Created for 4.2 BSD.
  316.  *
  317.  **********************************************************************
  318.  */
  319.  
  320. #define MSGFILE
  321. #include "supcdefs.h"
  322. #if    MACH
  323. #include <sys/syscall.h>
  324. #ifndef SYS_rpause
  325. #define SYS_rpause    (-5)
  326. #endif
  327. #endif
  328. #ifdef _ABI_SOURCE
  329. /*XXX #include <sys/time.h> */
  330. #include <sys/resource.h>
  331. #endif
  332.  
  333. /*********************************************
  334.  ***    G L O B A L   V A R I A B L E S    ***
  335.  *********************************************/
  336.  
  337. char program[] = "SUP";            /* program name for SCM messages */
  338. int progpid = -1;            /* and process id */
  339.  
  340. COLLECTION *firstC,*thisC;        /* collection list pointer */
  341.  
  342. extern int dontjump;            /* disable longjmp */
  343. extern int scmdebug;            /* SCM debugging flag */
  344.  
  345. int sysflag;                /* system upgrade flag */
  346. int timeflag;                /* print times flag */
  347. #if    MACH
  348. int rpauseflag;                /* don't disable resource pausing */
  349. #endif    /* MACH */
  350. int xpatchflag;                /* crosspatched with remote system */
  351. int portdebug;                /* network debugging ports */
  352.  
  353. /*************************************
  354.  ***    M A I N   R O U T I N E    ***
  355.  *************************************/
  356.  
  357. main (argc,argv)
  358. int argc;
  359. char **argv;
  360. {
  361.     char *init ();
  362.     char *progname,*supfname;
  363.     int restart,sfdev,sfino,sfmtime;
  364.     struct stat sbuf;
  365. #ifdef _ABI_SOURCE
  366.     struct sigaction ignvec,oldvec;
  367.     struct rlimit rl;
  368. #else
  369.     struct sigvec ignvec,oldvec;
  370. #endif
  371.  
  372.     /* initialize global variables */
  373.     pgmversion = PGMVERSION;    /* export version number */
  374.     server = FALSE;            /* export that we're not a server */
  375.     collname = NULL;        /* no current collection yet */
  376.     dontjump = TRUE;        /* clear setjmp buffer */
  377.     progname = salloc (argv[0]);
  378.  
  379.     supfname = init (argc,argv);
  380.     restart = -1;            /* don't make restart checks */
  381.     if (*progname == '/' && *supfname == '/') {
  382.         if (stat (supfname,&sbuf) < 0)
  383.             logerr ("Can't stat supfile %s",supfname);
  384.         else {
  385.             sfdev = sbuf.st_dev;
  386.             sfino = sbuf.st_ino;
  387.             sfmtime = sbuf.st_mtime;
  388.             restart = 0;
  389.         }
  390.     }
  391.     if (timeflag) {
  392.         for (thisC = firstC; thisC; thisC = thisC->Cnext)
  393.             prtime ();
  394.     } else {
  395.         /* ignore network pipe signals */
  396. #ifdef _ABI_SOURCE
  397.         ignvec.sa_handler = SIG_IGN;
  398.         ignvec.sa_flags = 0;
  399.         sigemptyset (&(ignvec.sa_mask));
  400.         (void) sigaction (SIGPIPE,&ignvec,&oldvec);
  401. #else
  402.         ignvec.sv_handler = SIG_IGN;
  403.         ignvec.sv_onstack = 0;
  404.         ignvec.sv_mask = 0;
  405.         (void) sigvec (SIGPIPE,&ignvec,&oldvec);
  406. #endif
  407.         getnams ();        /* find unknown repositories */
  408.         for (thisC = firstC; thisC; thisC = thisC->Cnext) {
  409.             getcoll ();    /* upgrade each collection */
  410.             if (restart == 0) {
  411.                 if (stat (supfname,&sbuf) < 0)
  412.                     logerr ("Can't stat supfile %s",
  413.                         supfname);
  414.                 else if (sfmtime != sbuf.st_mtime ||
  415.                      sfino != sbuf.st_ino ||
  416.                      sfdev != sbuf.st_dev) {
  417.                     restart = 1;
  418.                     break;
  419.                 }
  420.             }
  421.         }
  422.         endpwent ();        /* close /etc/passwd */
  423.         (void) endgrent ();    /* close /etc/group */
  424.         if (restart == 1) {
  425.             int fd;
  426.             loginfo ("SUP Restarting %s with new supfile %s",
  427.                 progname,supfname);
  428. #ifdef _ABI_SOURCE
  429.             getrlimit (RLIMIT_NOFILE, &rl);
  430.             for (fd = rl.rlim_max; fd > 3; fd--)
  431.                 (void) close (fd);
  432. #else
  433.             for (fd = getdtablesize (); fd > 3; fd--)
  434.                 (void) close (fd);
  435. #endif
  436.             execv (progname,argv);
  437.             logquit (1,"Restart failed");
  438.         }
  439.     }
  440.     while (thisC = firstC) {
  441.         firstC = firstC->Cnext;
  442.         free (thisC->Cname);
  443.         Tfree (&thisC->Chtree);
  444.         free (thisC->Cbase);
  445.         if (thisC->Chbase)  free (thisC->Chbase);
  446.         if (thisC->Cprefix)  free (thisC->Cprefix);
  447.         if (thisC->Crelease)  free (thisC->Crelease);
  448.         if (thisC->Cnotify)  free (thisC->Cnotify);
  449.         if (thisC->Clogin)  free (thisC->Clogin);
  450.         if (thisC->Cpswd)  free (thisC->Cpswd);
  451.         if (thisC->Ccrypt)  free (thisC->Ccrypt);
  452.         free ((char *)thisC);
  453.     }
  454.     exit (0);
  455. }
  456.  
  457. /*****************************************
  458.  ***    I N I T I A L I Z A T I O N    ***
  459.  *****************************************/
  460. /* Set up collection list from supfile.  Check all fields except
  461.  * hostname to be sure they make sense.
  462.  */
  463.  
  464. #define Toflags    Tflags
  465. #define Taflags    Tmode
  466. #define Twant    Tuid
  467. #define Tcount    Tgid
  468.  
  469. doswitch (argp,collTp,oflagsp,aflagsp)
  470. char *argp;
  471. register TREE **collTp;
  472. int *oflagsp,*aflagsp;
  473. {
  474.     register TREE *t;
  475.     register char *coll;
  476.     register int oflags,aflags;
  477.  
  478.     oflags = aflags = 0;
  479.     for (;;) {
  480.         switch (*argp) {
  481.         default:
  482.             logerr ("Invalid flag '%c' ignored",*argp);
  483.             break;
  484.         case '\0':
  485.         case '=':
  486.             if (*argp++ == '\0' || *argp == '\0') {
  487.                 *oflagsp |= oflags;
  488.                 *oflagsp &= ~aflags;
  489.                 *aflagsp |= aflags;
  490.                 *aflagsp &= ~oflags;
  491.                 return;
  492.             }
  493.             do {
  494.                 coll = nxtarg (&argp,", \t");
  495.                 t = Tinsert (collTp,coll,TRUE);
  496.                 t->Toflags |= oflags;
  497.                 t->Toflags &= ~aflags;
  498.                 t->Taflags |= aflags;
  499.                 t->Taflags &= ~oflags;
  500.                 argp = skipover (argp,", \t");
  501.             } while (*argp);
  502.             return;
  503.         case 'N':
  504.             scmdebug++;
  505.             break;
  506.         case 'P':
  507.             portdebug = TRUE;
  508.             break;
  509.         case 'R':
  510. #if    MACH
  511.             rpauseflag = TRUE;
  512. #endif    /* MACH */
  513.             break;
  514.         case 'X':
  515.             xpatchflag = TRUE;
  516.             break;
  517.         case 's':
  518.             sysflag = TRUE;
  519.             break;
  520.         case 't':
  521.             timeflag = TRUE;
  522.             break;
  523.         case 'a':
  524.             oflags |= CFALL;
  525.             break;
  526.         case 'b':
  527.             oflags |= CFBACKUP;
  528.             aflags &= ~CFBACKUP;
  529.             break;
  530.         case 'B':
  531.             oflags &= ~CFBACKUP;
  532.             aflags |= CFBACKUP;
  533.             break;
  534.         case 'd':
  535.             oflags |= CFDELETE;
  536.             aflags &= ~CFDELETE;
  537.             break;
  538.         case 'D':
  539.             oflags &= ~CFDELETE;
  540.             aflags |= CFDELETE;
  541.             break;
  542.         case 'e':
  543.             oflags |= CFEXECUTE;
  544.             aflags &= ~CFEXECUTE;
  545.             break;
  546.         case 'E':
  547.             oflags &= ~CFEXECUTE;
  548.             aflags |= CFEXECUTE;
  549.             break;
  550.         case 'f':
  551.             oflags |= CFLIST;
  552.             break;
  553.         case 'k':
  554.             oflags |= CFKEEP;
  555.             aflags &= ~CFKEEP;
  556.             break;
  557.         case 'K':
  558.             oflags &= ~CFKEEP;
  559.             aflags |= CFKEEP;
  560.             break;
  561.         case 'l':
  562.             oflags |= CFLOCAL;
  563.             break;
  564.         case 'm':
  565.             oflags |= CFMAIL;
  566.             break;
  567.         case 'o':
  568.             oflags |= CFOLD;
  569.             aflags &= ~CFOLD;
  570.             break;
  571.         case 'O':
  572.             oflags &= ~CFOLD;
  573.             aflags |= CFOLD;
  574.             break;
  575.         case 'v':
  576.             oflags |= CFVERBOSE;
  577.             break;
  578.         case 'z':
  579.             oflags |= CFCOMPRESS;
  580.             break;
  581.         case 'Z':
  582.             oflags &= ~CFCOMPRESS;
  583.             break;
  584.         }
  585.         argp++;
  586.     }
  587. }
  588.  
  589. char *init (argc,argv)
  590. int argc;
  591. char **argv;
  592. {
  593.     char buf[STRINGLENGTH],*p;
  594.     char username[STRINGLENGTH];
  595.     register char *supfname,*q,*arg;
  596.     register COLLECTION *c,*lastC;
  597.     register FILE *f;
  598.     register int bogus;
  599.     register struct passwd *pw;
  600.     register TREE *t;
  601.     TREE *collT;            /* collections we are interested in */
  602.     long timenow;            /* startup time */
  603.     int checkcoll ();
  604.     int oflags,aflags;
  605.     int cwant;
  606. #ifdef    MACH
  607. #ifdef    __STDC__
  608.     void (*oldsigsys)();
  609. #else
  610.     int (*oldsigsys)();
  611. #endif
  612. #endif /* MACH */
  613.     char *fmttime();
  614.  
  615.     sysflag = FALSE;        /* not system upgrade */
  616.     timeflag = FALSE;        /* don't print times */
  617. #if    MACH
  618.     rpauseflag = FALSE;        /* don't disable resource pausing */
  619. #endif    /* MACH */
  620.     xpatchflag = FALSE;        /* not normally crosspatched */
  621.     scmdebug = 0;            /* level zero, no SCM debugging */
  622.     portdebug = FALSE;        /* no debugging ports */
  623.  
  624.     collT = NULL;
  625.     oflags = aflags = 0;
  626.     while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
  627.         doswitch (&argv[1][1],&collT,&oflags,&aflags);
  628.         --argc;
  629.         argv++;
  630.     }
  631.     if (argc == 1 && !sysflag)
  632.         logquit (1,"Need either -s or supfile");
  633. #if    MACH
  634.     oldsigsys = signal (SIGSYS,SIG_IGN);
  635.     if (rpauseflag != TRUE)
  636.         if (syscall (SYS_rpause,ENOSPC,RPAUSE_ALL,RPAUSE_DISABLE) < 0)
  637.         rpauseflag = TRUE;
  638.     (void) signal (SIGSYS,oldsigsys);
  639. #endif    /* MACH */
  640.     if (sysflag)
  641.         (void) sprintf (supfname = buf,
  642.                     timeflag?FILESUPTDEFAULT:FILESUPDEFAULT,
  643.                     DEFDIR);
  644.     else {
  645.         supfname = argv[1];
  646.         if (strcmp (supfname,"-") == 0)
  647.             supfname = "";
  648.         --argc;
  649.         argv++;
  650.     }
  651.     cwant = argc > 1;
  652.     while (argc > 1) {
  653.         t = Tinsert (&collT,argv[1],TRUE);
  654.         t->Twant = TRUE;
  655.         --argc;
  656.         argv++;
  657.     }
  658.     if ((p = (char *)getlogin()) ||
  659.         ((pw = getpwuid ((int)getuid())) && (p = pw->pw_name)))
  660.         (void) strcpy (username,p);
  661.     else
  662.         *username = '\0';
  663.     if (*supfname) {
  664.         f = fopen (supfname,"r");
  665.         if (f == NULL)
  666.             logquit (1,"Can't open supfile %s",supfname);
  667.     } else
  668.         f = stdin;
  669.     firstC = NULL;
  670.     lastC = NULL;
  671.     bogus = FALSE;
  672.     while (p = fgets (buf,STRINGLENGTH,f)) {
  673.         q = index (p,'\n');
  674.         if (q)  *q = '\0';
  675.         if (index ("#;:",*p))  continue;
  676.         arg = nxtarg (&p," \t");
  677.         if (*arg == '\0') {
  678.             logerr ("Missing collection name in supfile");
  679.             bogus = TRUE;
  680.             continue;
  681.         }
  682.         if (cwant) {
  683.             register TREE *t;
  684.             if ((t = Tsearch (collT,arg)) == NULL)
  685.                 continue;
  686.             t->Tcount++;
  687.         }
  688.         c = (COLLECTION *) malloc (sizeof(COLLECTION));
  689.         if (firstC == NULL)  firstC = c;
  690.         if (lastC != NULL) lastC->Cnext = c;
  691.         lastC = c;
  692.         if (parsecoll(c,arg,p) < 0) {
  693.             bogus = TRUE;
  694.             continue;
  695.         }
  696.         c->Cflags |= oflags;
  697.         c->Cflags &= ~aflags;
  698.         if (t = Tsearch (collT,c->Cname)) {
  699.             c->Cflags |= t->Toflags;
  700.             c->Cflags &= ~t->Taflags;
  701.         }
  702.         if ((c->Cflags&CFMAIL) && c->Cnotify == NULL) {
  703.             if (*username == '\0')
  704.                 logerr ("User unknown, notification disabled");
  705.             else
  706.                 c->Cnotify = salloc (username);
  707.         }
  708.         if (c->Cbase == NULL) {
  709.             (void) sprintf (buf,FILEBASEDEFAULT,c->Cname);
  710.             c->Cbase = salloc (buf);
  711.         }
  712.     }
  713.     if (bogus)  logquit (1,"Aborted due to supfile errors");
  714.     if (f != stdin)  (void) fclose (f);
  715.     if (cwant)  (void) Tprocess (collT,checkcoll);
  716.     Tfree (&collT);
  717.     if (firstC == NULL)  logquit (1,"No collections to upgrade");
  718.     timenow = time ((long *)NULL);
  719.     if (*supfname == '\0')
  720.         p = "standard input";
  721.     else if (sysflag)
  722.         p = "system software";
  723.     else
  724.         (void) sprintf (p = buf,"file %s",supfname);
  725.     loginfo ("SUP %d.%d (%s) for %s at %s",PROTOVERSION,PGMVERSION,
  726.         scmversion,p,fmttime (timenow));
  727.     return (salloc (supfname));
  728. }
  729.  
  730. checkcoll (t)
  731. register TREE *t;
  732. {
  733.     if (!t->Twant)  return (SCMOK);
  734.     if (t->Tcount == 0)
  735.         logerr ("Collection %s not found",t->Tname);
  736.     if (t->Tcount > 1)
  737.         logerr ("Collection %s found more than once",t->Tname);
  738.     return (SCMOK);
  739. }
  740.